#include "comm/my_mem.h"
#include "comm/my_log.h"

void test_mem_freelist()
{
    my_mem_freelist_t list;
    my_mem_freelist_init(&list, 128, 3, my_mem_alloc, my_mem_free);

    void *p1 = my_mem_freelist_alloc(&list);
    void *p2 = my_mem_freelist_alloc(&list);
    void *p3 = my_mem_freelist_alloc(&list);
    void *p4 = my_mem_freelist_alloc(&list);
    void *p5 = my_mem_freelist_alloc(&list);
    void *p6 = my_mem_freelist_alloc(&list);

    my_mem_freelist_free(&list, p1);
    my_mem_freelist_free(&list, p2);
    my_mem_freelist_free(&list, p3);
    my_mem_freelist_free(&list, p4);
    my_mem_freelist_free(&list, p5);
    my_mem_freelist_free(&list, p6);

    p1 = my_mem_freelist_alloc(&list);
    p2 = my_mem_freelist_alloc(&list);
    p3 = my_mem_freelist_alloc(&list);
    p4 = my_mem_freelist_alloc(&list);
    p5 = my_mem_freelist_alloc(&list);
    p6 = my_mem_freelist_alloc(&list);

    my_mem_freelist_free(&list, p1);
    my_mem_freelist_free(&list, p2);
    my_mem_freelist_free(&list, p3);
    my_mem_freelist_free(&list, p4);
    my_mem_freelist_free(&list, p5);
    my_mem_freelist_free(&list, p6);

    my_mem_freelist_clean(&list);
}

void test_mem_pool()
{
    my_mem_pool_t mem_pool;
    my_mem_pool_init(&mem_pool, 3, my_mem_alloc, my_mem_free);

    void *p1 = my_mem_pool_alloc(&mem_pool, 32);
    void *p2 = my_mem_pool_alloc(&mem_pool, 33);
    void *p3 = my_mem_pool_alloc(&mem_pool, 65);
    void *p4 = my_mem_pool_alloc(&mem_pool, 129);
    void *p5 = my_mem_pool_alloc(&mem_pool, 257);
    void *p6 = my_mem_pool_alloc(&mem_pool, 513);
    void *p7 = my_mem_pool_alloc(&mem_pool, 1025);
    void *p8 = my_mem_pool_alloc(&mem_pool, 2048);
    void *p9 = my_mem_pool_alloc(&mem_pool, 4096);
    void *p10 = my_mem_pool_alloc(&mem_pool, 8192);
    void *p11 = my_mem_pool_alloc(&mem_pool, 16384);

    my_mem_pool_free(&mem_pool, p11);
    my_mem_pool_free(&mem_pool, p10);
    my_mem_pool_free(&mem_pool, p9);
    my_mem_pool_free(&mem_pool, p8);
    my_mem_pool_free(&mem_pool, p7);
    my_mem_pool_free(&mem_pool, p6);
    my_mem_pool_free(&mem_pool, p5);
    my_mem_pool_free(&mem_pool, p4);
    my_mem_pool_free(&mem_pool, p3);
    my_mem_pool_free(&mem_pool, p2);
    my_mem_pool_free(&mem_pool, p1);

    my_mem_pool_clean(&mem_pool);
}

void test_g_mem_pool()
{
    void *p1 = my_mem_pool_alloc(&g_mem_pool, 32);
    void *p2 = my_mem_pool_alloc(&g_mem_pool, 33);
    void *p3 = my_mem_pool_alloc(&g_mem_pool, 65);
    void *p4 = my_mem_pool_alloc(&g_mem_pool, 129);
    void *p5 = my_mem_pool_alloc(&g_mem_pool, 257);
    void *p6 = my_mem_pool_alloc(&g_mem_pool, 513);
    void *p7 = my_mem_pool_alloc(&g_mem_pool, 1025);
    void *p8 = my_mem_pool_alloc(&g_mem_pool, 2048);
    void *p9 = my_mem_pool_alloc(&g_mem_pool, 4096);
    void *p10 = my_mem_pool_alloc(&g_mem_pool, 8192);
    void *p11 = my_mem_pool_alloc(&g_mem_pool, 16384);

    my_mem_pool_free(&g_mem_pool, p11);
    my_mem_pool_free(&g_mem_pool, p10);
    my_mem_pool_free(&g_mem_pool, p9);
    my_mem_pool_free(&g_mem_pool, p8);

    my_mem_pool_init(&g_mem_pool, 3, my_mem_alloc, my_mem_free);

    my_mem_pool_free(&g_mem_pool, p7);
    my_mem_pool_free(&g_mem_pool, p6);
    my_mem_pool_free(&g_mem_pool, p5);
    my_mem_pool_free(&g_mem_pool, p4);
    my_mem_pool_free(&g_mem_pool, p3);
    my_mem_pool_free(&g_mem_pool, p2);
    my_mem_pool_free(&g_mem_pool, p1);

    p1 = my_mem_pool_alloc(&g_mem_pool, 32);
    p2 = my_mem_pool_alloc(&g_mem_pool, 33);
    p3 = my_mem_pool_alloc(&g_mem_pool, 65);
    p4 = my_mem_pool_alloc(&g_mem_pool, 129);
    p5 = my_mem_pool_alloc(&g_mem_pool, 257);
    p6 = my_mem_pool_alloc(&g_mem_pool, 513);
    p7 = my_mem_pool_alloc(&g_mem_pool, 1025);
    p8 = my_mem_pool_alloc(&g_mem_pool, 2048);
    p9 = my_mem_pool_alloc(&g_mem_pool, 4096);
    p10 = my_mem_pool_alloc(&g_mem_pool, 8192);
    p11 = my_mem_pool_alloc(&g_mem_pool, 16384);

    my_mem_pool_free(&g_mem_pool, p11);
    my_mem_pool_free(&g_mem_pool, p10);
    my_mem_pool_free(&g_mem_pool, p9);
    my_mem_pool_free(&g_mem_pool, p8);
    my_mem_pool_free(&g_mem_pool, p7);
    my_mem_pool_free(&g_mem_pool, p6);
    my_mem_pool_free(&g_mem_pool, p5);
    my_mem_pool_free(&g_mem_pool, p4);
    my_mem_pool_free(&g_mem_pool, p3);
    my_mem_pool_free(&g_mem_pool, p2);
    my_mem_pool_free(&g_mem_pool, p1);

    p1 = my_mem_pool_alloc(&g_mem_pool, 32);
    p2 = my_mem_pool_alloc(&g_mem_pool, 33);
    p3 = my_mem_pool_alloc(&g_mem_pool, 65);
    p4 = my_mem_pool_alloc(&g_mem_pool, 129);
    p5 = my_mem_pool_alloc(&g_mem_pool, 257);
    p6 = my_mem_pool_alloc(&g_mem_pool, 513);
    p7 = my_mem_pool_alloc(&g_mem_pool, 1025);
    p8 = my_mem_pool_alloc(&g_mem_pool, 2048);
    p9 = my_mem_pool_alloc(&g_mem_pool, 4096);
    p10 = my_mem_pool_alloc(&g_mem_pool, 8192);
    p11 = my_mem_pool_alloc(&g_mem_pool, 16384);

    my_mem_pool_free(&g_mem_pool, p11);
    my_mem_pool_free(&g_mem_pool, p10);
    my_mem_pool_free(&g_mem_pool, p9);
    my_mem_pool_free(&g_mem_pool, p8);
    my_mem_pool_free(&g_mem_pool, p7);
    my_mem_pool_free(&g_mem_pool, p6);
    my_mem_pool_free(&g_mem_pool, p5);
    my_mem_pool_free(&g_mem_pool, p4);
    my_mem_pool_free(&g_mem_pool, p3);
    my_mem_pool_free(&g_mem_pool, p2);
    my_mem_pool_free(&g_mem_pool, p1);

    my_mem_pool_clean(&g_mem_pool);
}

void test_aligned_mem_freelist()
{
    my_4kaligned_mem_freelist_t list;
    my_4kaligned_mem_freelist_init(&list, 128, 3,
        my_aligned_malloc, my_aligned_free);

    void *p1 = my_4kaligned_mem_freelist_alloc(&list);
    void *p2 = my_4kaligned_mem_freelist_alloc(&list);
    void *p3 = my_4kaligned_mem_freelist_alloc(&list);
    void *p4 = my_4kaligned_mem_freelist_alloc(&list);
    void *p5 = my_4kaligned_mem_freelist_alloc(&list);
    void *p6 = my_4kaligned_mem_freelist_alloc(&list);

    my_4kaligned_mem_freelist_free(&list, p1);
    my_4kaligned_mem_freelist_free(&list, p2);
    my_4kaligned_mem_freelist_free(&list, p3);
    my_4kaligned_mem_freelist_free(&list, p4);
    my_4kaligned_mem_freelist_free(&list, p5);
    my_4kaligned_mem_freelist_free(&list, p6);

    p1 = my_4kaligned_mem_freelist_alloc(&list);
    p2 = my_4kaligned_mem_freelist_alloc(&list);
    p3 = my_4kaligned_mem_freelist_alloc(&list);
    p4 = my_4kaligned_mem_freelist_alloc(&list);
    p5 = my_4kaligned_mem_freelist_alloc(&list);
    p6 = my_4kaligned_mem_freelist_alloc(&list);

    my_4kaligned_mem_freelist_free(&list, p1);
    my_4kaligned_mem_freelist_free(&list, p2);
    my_4kaligned_mem_freelist_free(&list, p3);
    my_4kaligned_mem_freelist_free(&list, p4);
    my_4kaligned_mem_freelist_free(&list, p5);
    my_4kaligned_mem_freelist_free(&list, p6);

    my_4kaligned_mem_freelist_clean(&list);
}

void test_g_aligned_mem_pool()
{
    void *p1 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 32 * 1024);
    void *p2 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 33 * 1024);
    void *p3 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 65 * 1024);
    void *p4 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 129 * 1024);
    void *p5 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 257 * 1024);
    void *p6 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 513 * 1024);
    void *p7 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 1025 * 1024);
    void *p8 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 2048 * 1024);
    void *p9 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 4096 * 1024);
    void *p10 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 8192 * 1024);
    void *p11 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 16384 * 1024);

    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p11);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p10);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p9);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p8);

    my_4kaligned_mem_pool_init(&g_4kaligned_mem_pool, 3,
        my_aligned_malloc, my_aligned_free);

    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p7);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p6);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p5);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p4);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p3);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p2);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p1);

    p1 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 32 * 1024);
    p2 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 33 * 1024);
    p3 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 65 * 1024);
    p4 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 129 * 1024);
    p5 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 257 * 1024);
    p6 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 513 * 1024);
    p7 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 1025 * 1024);
    p8 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 2048 * 1024);
    p9 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 4096 * 1024);
    p10 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 8192 * 1024);
    p11 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 16384 * 1024);

    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p11);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p10);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p9);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p8);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p7);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p6);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p5);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p4);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p3);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p2);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p1);

    p1 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 32 * 1024);
    p2 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 33 * 1024);
    p3 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 65 * 1024);
    p4 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 129 * 1024);
    p5 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 257 * 1024);
    p6 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 513 * 1024);
    p7 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 1025 * 1024);
    p8 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 2048 * 1024);
    p9 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 4096 * 1024);
    p10 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 8192 * 1024);
    p11 = my_4kaligned_mem_pool_alloc(&g_4kaligned_mem_pool, 16384 * 1024);

    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p11);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p10);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p9);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p8);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p7);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p6);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p5);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p4);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p3);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p2);
    my_4kaligned_mem_pool_free(&g_4kaligned_mem_pool, p1);

    my_4kaligned_mem_pool_clean(&g_4kaligned_mem_pool);
}

int main()
{
    // test_mem_freelist();
    // test_mem_pool();
    // test_g_mem_pool();

    // test_aligned_mem_freelist();
    test_g_aligned_mem_pool();

    my_mem_assert_leak();

    MY_LOG_DEBUG("test pass");
}